package main

import (
	"fmt"
	"github.com/ethereum/go-ethereum/accounts/abi/bind"
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/ethclient"
	"log"
	"os"
	"xuanshang/ethdemo_test/hello"
)

const (
	ACCOUNTKEYPATH = `//home/zf/devdata/keystore/UTC--2022-08-06T07-39-54.806510269Z--6094aaf79f614f577ed111195f5e9ecdfbc96d93`
	PASSWD         = "12345678"
)

func main() {
	// 1. 连接到节点
	ethCli, err := ethclient.Dial("http://127.0.0.1:8545")
	if err != nil {
		log.Panic("dial ethClient failed!", err)
	}
	defer ethCli.Close()
	// 2. 创建合约实例(需要的参数：合约地址+节点，合约地址可在 Remix 环境已部署的合约中查看)
	instance, err := hello.NewHello(common.HexToAddress("0xF7A03c7A907ed991fC9884C1EfBCf7B0CE78C78F"), ethCli)
	if err != nil {
		log.Panic("failed to NewHello", err)
	}
	// 3. 函数调用
	opts := &bind.CallOpts{
		// 该地址为调用智能合约的地址
		From: common.HexToAddress("0x6094aaf79f614f577ed111195f5e9ecdfbc96d93"),
	}
	strmsg, err := instance.GetMsg(opts)
	if err != nil {
		fmt.Println(err)
		log.Panic("failed to GetMsg", err)
	}
	fmt.Println("getMsg:", strmsg)

	// 4. 调用消耗 gas 的函数
	/*
		- 调用需要消耗 gas 的函数首先需要构造一个 TransactOpts 结构，结构体字段内容如下：
		```GO
		type TransactOpts struct {
			From   common.Address   // 谁来调用函数的地址
			Nonce  *big.Int         // 当前账户交易的交易编号，该值对某个账户来说必须唯一
			Signer SignerFn         // 签名信息
			Value    *big.Int 	    // 本次交易账户携带的以太数量
			GasPrice *big.Int       // 该笔交易消耗的 gas 价格
			GasLimit uint64         // 该笔交易的 gas 上限值
			Context context.Context // 网络套接字上下文
		}
		```
		- 在 `go-ethereum` 保中为我们提供了一个专门用来构造喊结构体的方法，包路径为 `go-ethereum/accounts/abi/bind` 原型如下：
			```go
			func NewTransactor(keyin io.Reader, passphrase string) (*TransactOpts, error) {}
			```
			- 参数说明：
				- 参数一：`keyin`：读取到的用来保存账户私钥文件，该文件保存在我们启动 geth 时 `--datadir` 参数指定目录下的 `keystore` 文件夹内
		文件格式为：
					```shell
					UTC--2022-08-04T13-56-37.896588642Z--去除 0x 后的账户地址
					```
				- 参数二： `passphrase`：创建账户时设置的密码
	*/
	// 4.1. 打开文件拿到 reader 对象
	file, err := os.Open(ACCOUNTKEYPATH)
	if err != nil {
		log.Panic("openFile failed:", err)
	}
	defer file.Close()
	auth, err := bind.NewTransactor(file, PASSWD)
	if err != nil {
		log.Panic("failed to NewTransactor", err)
	}
	// 4.3. 开始调用消费 gas 函数
	_, err = instance.SetMsg(auth, "zhufeng")
	if err != nil {
		log.Panic("failed to SetMsg", err)
	}
}
